package com.t.bricks.bussiness.component.userandright;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.t.bricks.bussiness.db.mapper.userandright.UserAndRightMapper;
import com.t.bricks.bussiness.service.userandright.UserAndRightService;
import com.t.bricks.model.Log;
import com.t.bricks.model.MsgEmity;
import com.t.bricks.utils.spring.ModuleUtil;

/**
 * 用切面方式监听有关人员与权限信息相关的数据操作
 */
@Aspect
@Component
public class UserAndRightMapperAspect {
		
	@Autowired
	private UserAndRightMapper userAndRightMapper;
	
	@Autowired
	private UserAndRightService userAndRightService;

	/**
	 * 定义切入点，切入点返回值为'MsgEmity'类型
	 * 切入点为 登录用户信息、部门信息的删除函数，并且要求被切面的函数与监听的参数一致
	 */
	@Pointcut(value = "execution(com.t.bricks.model.MsgEmity com.t.bricks.bussiness.service.loginuser.impl.LoginUserService*.del(Integer,String))"
			+ " || execution(int com.t.bricks.bussiness.db.mapper.department.DepartmentMapper.del(String,Integer))")
	public void delMethod() {
	}

	/**
	 * 定义切入点，切入点返回值为'MsgEmity'类型
	 * 切入点为 登录用户信息、人员信息、部门信息的删除函数，并且要求被切面的函数与监听的参数一致
	 */
	@Pointcut(value = "execution(com.t.bricks.model.MsgEmity com.t.bricks.bussiness.service.rightmanage.impl.RightManageService*.del(Integer,String))"
			+ " || execution(com.t.bricks.model.MsgEmity com.t.bricks.bussiness.service.rightmanage.impl.RightManageService*.edit(..))")
	public void delAllMethod() {
	}
	
	/**
	 * 定义切入点，切入点返回值为'MsgEmity'类型
	 * 切入点为 角色表/ 角色与权限关系表 发生变化的函数，并且要求被切面的函数与监听的参数一致
	 */
	@Pointcut(value = "execution(com.t.bricks.model.MsgEmity com.t.bricks.bussiness.service.roleandright.impl.RoleAndRightService*.add(String,String))"
			+ " || execution(com.t.bricks.model.MsgEmity com.t.bricks.bussiness.service.role.impl.RoleService*.del(Integer,String))")
	public void roleMethod() {
	}
	
	/**
	 * 定义切入点，切入点返回值为'MsgEmity'类型
	 * 切入点为 用户与权限关联的保存函数，并且要求被切面的函数与监听的参数一致
	 */
	@Pointcut(value = "execution(com.t.bricks.model.MsgEmity com.t.bricks.bussiness.service.userandrole.impl.UserAndRoleServiceImpl*.add(String,String))")
	public void relRoleMethod() {
	}

	/**
	 * 后置/返回值增强
     * @param joinPoint
     * @param result 被切点方法执行后的返回值
     * @return
	 */
	@AfterReturning(returning="result", pointcut="delMethod()")
	public void afterReturningByDel(JoinPoint joinPoint, Object result) {
		if (!check(joinPoint, result)) {
			return;
		}

		Object[] methodArgs = joinPoint.getArgs();
		String sUserId = String.valueOf(methodArgs[1]);

		ModuleUtil.runThread(() -> {//多线程方式重新构造缓存数据
			userAndRightMapper.delDiscard();			//清理已经废弃的信息
			userAndRightService.clearCache(sUserId);	//清除缓存
		});
	}

	/**
	 * 后置/返回值增强
     * @param joinPoint
     * @param result 被切点方法执行后的返回值
     * @return
	 */
	@AfterReturning(returning="result", pointcut="delAllMethod()")
	public void afterReturningByDelAll(JoinPoint joinPoint, Object result) {
		if (!check(joinPoint, result)) {
			return;
		}

		ModuleUtil.runThread(() -> {//多线程方式重新构造缓存数据
			userAndRightMapper.delDiscard();		//清理已经废弃的信息
			userAndRightService.clearCache(null);	//清除缓存
		});
	}
	
	/**
	 * 后置/返回值增强
     * @param joinPoint
     * @param result 被切点方法执行后的返回值
     * @return
	 */
	@AfterReturning(returning="result", pointcut="roleMethod()")
	public void afterReturningByAdd(JoinPoint joinPoint, Object result) {
		if (!check(joinPoint, result)) {
			return;
		}

		ModuleUtil.runThread(() -> {//多线程方式重新构造缓存数据
			userAndRightService.clearCache(null);	//清理已经废弃的信息
			userAndRightService.clearCache(null);	//清除缓存
		});
	}

	/**
	 * 后置/返回值增强
     * @param joinPoint
     * @param result 被切点方法执行后的返回值
     * @return
	 */
	@AfterReturning(returning="result", pointcut="relRoleMethod()")
	public void afterReturningByRelRole(JoinPoint joinPoint, Object result) {
		if (!check(joinPoint, result)) {
			return;
		}

		Object[] methodArgs = joinPoint.getArgs();
		if (methodArgs.length < 1 || null == methodArgs[0]) {
			return;
		}
		
		String sUserId = String.valueOf(methodArgs[0]);

		ModuleUtil.runThread(() -> {//多线程方式重新构造缓存数据
			userAndRightService.clearCache(null);			//清理已经废弃的信息
			userAndRightService.clearCache(sUserId);		//清除缓存
		});
	}

	/**
	 * 后置/返回值增强
     * @param joinPoint
     * @param result 被切点方法执行后的返回值
     * @return
	 */
	private boolean check(JoinPoint joinPoint, Object result) {
		if (!(result instanceof MsgEmity)) {//不是返回MsgEmity,则说明不是要进行的
			MethodSignature signature = (MethodSignature) joinPoint.getSignature();
			String methodName = signature.getMethod().getName();
			Log.error("方法'", methodName, "'返回数据不是MsgEmity");
			return false;
		}

		return ((MsgEmity)result).isSuccess();
	}
		
}
